#include "include/ConfigIni.h"
#include <filesystem>
#include <fstream>
#include <sstream>
#include <variant>

namespace Tool
{
ConfigIni::ConfigIni()
{
}

ConfigIni::~ConfigIni()
{
}

void ConfigIni::Load(const std::string& path)
{
    std::ifstream file(path);
    if (!file.is_open())
    {
        std::cerr << "Failed to Load path: " << path << std::endl;
        return;
    }

    std::string line;
    std::string current_group;
    while (std::getline(file, line))
    {
        line = Trim(line); // 假设Trim是一个去除首尾空白字符的函数
        if (!line.empty()) // 确保处理前检查是否为空
        {
            if (line.front() == '[' && line.back() == ']')
            {
                current_group = line.substr(1, line.size() - 2);
            }
            else if (!current_group.empty())
            {
                size_t pos = line.find('=');
                if (pos != std::string::npos)
                {
                    std::string key = Trim(line.substr(0, pos));
                    std::string value_str = Trim(line.substr(pos + 1));
                    if (!key.empty())
                    {
                        m_config[current_group][key] = ParseVariant(value_str);
                    }
                }
            }
        }
    }
}

std::string ConfigIni::Trim(const std::string& str)
{
    const auto strBegin = str.find_first_not_of(" \t");
    if (strBegin == std::string::npos) return "";

    const auto strEnd = str.find_last_not_of(" \t");
    const auto strRange = strEnd - strBegin + 1;

    return str.substr(strBegin, strRange);
}

void ConfigIni::Save(const std::string &path)
{
    std::filesystem::path p(path);
    if (!p.parent_path().empty())
    {
        if (!std::filesystem::exists(p.parent_path()))
        {
            if (std::filesystem::create_directories(p.parent_path()))
            {
                std::cout << "Directories created: " << p.parent_path() << std::endl;
            }
            else
            {
                std::cerr << "Failed to create directories: " << p.parent_path() << std::endl;
                return;
            }
        }
    }

    std::ofstream file(path);
    if (!file.is_open())
    {
        std::cerr << "Failed to Save path: " << path << std::endl;
        return;
    }


    for (const auto &[group, groupConfig] : m_config.RefValue<Tool::VariantHash>())
    {
        file << "[" << group << "]\n";
        for (const auto &[key, value] : groupConfig.RefValue<Tool::VariantHash>())
        {
            file << key << "=" << ToString(value) << "\n";
        }
        file << "\n";
    }
}

Variant ConfigIni::ParseVariant(const std::string &str)
{
    if (str == "true" || str == "TRUE")
    {
        return true;
    }
    if (str == "false" || str == "FALSE")
    {
        return false;
    }
    try
    {
        size_t pos;
        int intValue = std::stoi(str, &pos);
        if (pos == str.size())
        {
            return intValue;
        }
    }
    catch (...)
    {
    }

    try
    {
        size_t pos;
        double doubleValue = std::stod(str, &pos);
        if (pos == str.size())
        {
            return doubleValue;
        }
    }
    catch (...)
    {
    }

    return str;
}

std::string ConfigIni::ToString(const Variant &var)
{
    std::ostringstream oss;
    if(var.Type() == VariantType::Int)
    {
        oss << var.ToInt();
    }
    else if(var.Type() == VariantType::Bool)
    {
        oss << (var.ToBool() ? "true" : "false");
    }
    else if(var.Type() == VariantType::Float)
    {
        oss << std::fixed << std::setprecision(6) << var.ToFloat();
    }
    else if(var.Type() == VariantType::Double)
    {
        oss << std::fixed << std::setprecision(6) << var.ToDouble();
    }
    else if(var.Type() == VariantType::String)
    {
        oss << var.ToString();
    }
    else
    {
        oss << "unknown";
    }
    return oss.str();
}
}
